﻿
// ———————————————————————–
// <copyright file="LocationCylinderGenerator.cs" company="The MITRE Corporation">
//    Copyright (c) 2014 The MITRE Corporation. All rights reserved.
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// </copyright>
// ———————————————————————–
/////////////////////////////////////////////////////////////////////////////////////////////////
// LocationCylinderGenerator.cs:
//
// A generator for good and bad examples of LocationCylinder.
//
// Project: NIEMCADTest
// Author:  Lizzie DeYoung - MITRE
/////////////////////////////////////////////////////////////////////////////////////////////////

// Copyright (c) 2014 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)  
      

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace NIEMCADTest.EventTests
{
  public class LocationCylinderGenerator : Generator
  {
    public const string POINT_SUB = "$point$";
    public const string RAD_SUB = "$radius$";
    public const string HEIGHT_SUB = "$halfheight$";
    public const string CREATION_CODE_SUB = "$creationcode$";
    public const string CONTENT_SUB = "$content$";
    public const string INNER_NAME_SUB = "$innername$";

    public const string RADIUS = "LocationCylinderRadiusValue";
    public const string HEIGHT = "LocationCylinderHalfHeightValue";

    public const string INNER = @"
    <$prefix$:$innername$ xmlns:$prefix$='$namespace$'>
      $content$
    </$prefix$:$innername$>";

    public const string LOCATION_CYLINDER = @"
    <$prefix$:$name$ xmlns:$prefix$='$namespace$'>
      $point$
      $radius$
      $halfheight$
      $creationcode$
    </$prefix$:$name$>";

    public const string WRONG_ELEMENT_NAME = @"
    <$prefix$:asdf xmlns:$prefix$='$namespace$'>
      $point$
      $radius$
      $halfheight$
      $creationcode$
    </$prefix$:asdf>";

    public string[] GOOD_DEC = new string[3] { "-123.1234", "0", "123.1234" };
    //TODO: TEST check if +123 should be invalid.
    public string[] BAD_DEC = new string[2] { "asdf", /* should this be invalid? it's not "+123",*/ "*123" };

    public LocationCylinderGenerator()
    {
      elementNamespace = "http://example.com/milops/1.1/";
      elementName = "LocationCylinder";
      elementPrefix = "mof";
    }

    public List<TestObject> BAD_WrongElementName()
    {
      List<TestObject> list = new List<TestObject>();
      TestObject pointTestObject = TestHelper.GetAGoodTestObject(typeof(LocationPointGenerator));
      string xml = GetXml(WRONG_ELEMENT_NAME, pointTestObject, RADIUS, HEIGHT, GOOD_DEC[0], GOOD_DEC[0]);
      TestObject testObject = GetTestObject(xml);

      list.Add(testObject);

      return list;
    }

    public List<TestObject> BAD_MultipleElements()
    {

      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      TestObject pointTestObject = TestHelper.GetAGoodTestObject(typeof(LocationPointGenerator));

      // repeat point
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, GOOD_DEC[0], GOOD_DEC[0],
        true, false, false);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // repeat radius
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, GOOD_DEC[0], GOOD_DEC[0],
        false, true, false);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // repeat height
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, GOOD_DEC[0], GOOD_DEC[0],
        false, false, true);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      return list;
    }

    public List<TestObject> BAD_MissingElements()
    {
      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      TestObject pointTestObject = TestHelper.GetAGoodTestObject(typeof(LocationPointGenerator));

      // no elements
      xml = GetXml(LOCATION_CYLINDER, null, null, null, GOOD_DEC[0], GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no point element
      xml = GetXml(LOCATION_CYLINDER, null, RADIUS, HEIGHT, GOOD_DEC[0], GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no radius element
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, null, HEIGHT, GOOD_DEC[0], GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no height element
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, null, GOOD_DEC[0], GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no radius content
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, "", GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // no height content
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, GOOD_DEC[0], "");
      testObject = GetTestObject(xml);
      list.Add(testObject);

      return list;
    }

    public List<TestObject> BAD_BadContent()
    {
      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;

      TestObject pointTestObject = TestHelper.GetAGoodTestObject(typeof(LocationPointGenerator));
      List<TestObject> badPointList = TestHelper.GetBadTestObjects(typeof(LocationPointGenerator));

      // bad point
      foreach (TestObject to in badPointList)
      {
        xml = GetXml(LOCATION_CYLINDER, to, RADIUS, HEIGHT, GOOD_DEC[0], GOOD_DEC[0]);
        testObject = GetTestObject(xml);
        list.Add(testObject);
      }

      // bad radius name
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, "asdf", HEIGHT, GOOD_DEC[0], GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // bad height name
      xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, "asdf", GOOD_DEC[0], GOOD_DEC[0]);
      testObject = GetTestObject(xml);
      list.Add(testObject);

      // bad radius value
      foreach (string badValue in BAD_DEC)
      {
        xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, badValue, GOOD_DEC[0]);
        testObject = GetTestObject(xml);
        list.Add(testObject);
      }

      // bad height value
      foreach (string badValue in BAD_DEC)
      {
        xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, GOOD_DEC[0], badValue);
        testObject = GetTestObject(xml);
        list.Add(testObject);
      }

      return list;
    }

    public List<TestObject> GOOD_GoodContent()
    {
      List<TestObject> list = new List<TestObject>();
      string xml;
      TestObject testObject;
      List<TestObject> goodPointList = TestHelper.GetGoodTestObjects(typeof(LocationPointGenerator));

      // good content
      foreach (TestObject pointTestObject in goodPointList)
      {
        foreach (string radiusValue in GOOD_DEC)
        {
          foreach (string heightValue in GOOD_DEC)
          {
            xml = GetXml(LOCATION_CYLINDER, pointTestObject, RADIUS, HEIGHT, radiusValue, heightValue);
            testObject = GetTestObject(xml);
            list.Add(testObject);
          }
        }
      }

      return list;
    }

    protected override string GetXml(string xml)
    {
      xml = base.GetXml(xml).Replace(CREATION_CODE_SUB, "");

      return xml;
    }

    private string GetXml(string xml, TestObject locationPointTestObject, string radiusElement, string heightElement, 
      string radiusContent, string heightContent,
      bool repeatLocationPoint = false, bool repeatRadius = false, bool repeatHeight = false)
    {
      string radiusXml = "";
      if (radiusElement != null)
      {
        radiusXml = GetXml(INNER).Replace(INNER_NAME_SUB, radiusElement).Replace(CONTENT_SUB, radiusContent);
        if (repeatRadius)
        {
          radiusXml += radiusXml;
        }
      }
      string heightXml = "";
      if (heightElement != null)
      {
        heightXml = GetXml(INNER).Replace(INNER_NAME_SUB, heightElement).Replace(CONTENT_SUB, heightContent);
        if (repeatHeight)
        {
          heightXml += heightXml;
        }
      }

      string locationPointContent;
      if (locationPointTestObject == null)
      {
        locationPointContent = "";
      } else {
        locationPointContent = locationPointTestObject.Xml.OuterXml;
        if (repeatLocationPoint)
        {
          locationPointContent += locationPointContent;
        }
      }

      string cylinderXml = GetXml(xml).Replace(
        POINT_SUB, locationPointContent).Replace(
        RAD_SUB, radiusXml).Replace(
        HEIGHT_SUB, heightXml);

      return cylinderXml;
    }
  }
}
